﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.IO;


namespace tswe.umbraco.languageEditor.classes.xml
{
    [XmlRoot("language")]
    public class Language
    {
        [XmlAttribute(AttributeName = "alias", DataType = "string")]
        public string Alias;

        [XmlAttribute(AttributeName = "intName", DataType = "string")]
        public string IntName;

        [XmlAttribute(AttributeName = "lcid", DataType = "string")]
        public string LcId;

        [XmlAttribute(AttributeName = "culture", DataType = "string")]
        public string Culture;

        [XmlElement("creator")]
        public Creator Creator = new Creator();

        [XmlElement("area", typeof(Area))]
        public List<Area> Areas = new List<Area>();


        /// <summary>
        /// Die aktuellen Eigenschaften des Objekts werden 
        /// in eine Datei im XML-Format geschrieben.
        /// </summary>
        /// <param name="fileName">Der Dateiname der Datei in die das Objekt 
        /// seine Eigenschaften schreibt</param>
        public void Save(string fileName)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Language));
            XmlTextWriter xmlTextWriter = new XmlTextWriter(fileName,
                    new System.Text.UTF8Encoding());
            xmlTextWriter.Formatting = Formatting.Indented;
            try
            {
                xmlSerializer.Serialize(xmlTextWriter, this);
            }
            finally
            {
                xmlTextWriter.Close();
            }
        }

        /// <summary>
        /// Die statische Klassenmethode erstellt ein neues ScanTask Objekt.
        /// Die aktuellen Eigenschaften werden dazu aus einer Datei im XML-Format geladen.
        /// </summary>
        /// <param name="fileName">Dateiname, aus dem die Eigenschaften gelesen werden</param>
        /// <returns> liefert ein neues Objekt oder mit den aus fileName geladenen Eigenschaften</returns>
        static public Language Load(string fileName)
        {
            if (System.IO.File.Exists(fileName))
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(Language));
                FileStream fileStream = new FileStream(fileName, FileMode.Open);
                XmlTextReader xmlTextReader = new XmlTextReader(fileStream);
                Language instance;
                try
                {
                    instance = (Language)xmlSerializer.Deserialize(xmlTextReader);
                }
                finally
                {
                    xmlTextReader.Close();
                }
                return instance;
            }
            else return new Language();
        }

        private string lastAreaAlias = null;
        private string lastKeyAlias = null;

        public string Text(string areaAlias, string keyAlias)
        {
            lastAreaAlias = areaAlias;
            lastKeyAlias = keyAlias;

            foreach (Area area in Areas)
                if (area.Alias == areaAlias)
                    foreach (Key key in area.Keys)
                        if (key.Alias == keyAlias)
                            return key.Value;
            return String.Empty;
        }

        internal void UpdateLastKey(string text)
        {
            if (lastAreaAlias == null || lastKeyAlias == null)
                return;

            foreach (Area area in Areas)
            {
                if (area.Alias == lastAreaAlias)
                {
                    foreach (Key key in area.Keys)
                        if (key.Alias == lastKeyAlias)
                        {
                            key.Value = text;
                            return;
                        }
                    // key not found
                    addKeyToArea(area, lastKeyAlias, text);
                    return;
                }
            }
            // area not found
            Area newArea = addArea(lastAreaAlias);
            addKeyToArea(newArea, lastKeyAlias, text);
        }

        /// <summary>
        /// tidy up this language areas to match other language areas order
        /// and will remove empty areas
        /// </summary>
        /// <param name="other"></param>
        /// <returns>false: this language has no areas inside</returns>
        public bool TidyUpBy(Language other)
        {
            bool hasArea = false;
            int index = 0;
            foreach (Area otherArea in other.Areas)
            {
                int areaIndex = findIndex(otherArea.Alias);
                if (areaIndex < 0) continue;

                Area thisArea = Areas[areaIndex];
                Areas.RemoveAt(areaIndex);

                if (!thisArea.TidyUpBy(otherArea)) continue;

                Areas.Insert(index, thisArea);
                hasArea = true;
                index++;
            }
            for (int i = Areas.Count - 1; i >= index; i--)
                Areas.RemoveAt(i);


            return hasArea;
        }

        private int findIndex(string alias)
        {
            int index = 0;
            foreach (Area area in Areas)
            {
                if (area.Alias == alias)
                    return index;
                index++;
            }
            return -1;
        }

        private Area addArea(string alias)
        {
            Area area = new Area();
            area.Alias = alias;
            Areas.Add(area);
            return area;
        }

        private void addKeyToArea(Area area, string alias, string value)
        {
            Key key = new Key();
            key.Alias = alias;
            key.Value = value;
            area.Keys.Add(key);
        }
    }
}
